package com.yuke.cloud.zuul.util;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.MimeHeaders;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;

/*
 * <p>Company: Copyright (c) 2018. yuke All Rights Reserved. </br> </p>
 * <p>Title：yukemall </br> </p>
 * <p>com.yuke.cloud.common.util Description TODO </br> </p>
 * @Author wg
 * @Date   2019/1/7 10:04
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class HttpUtil {

    /**
     * 循环向上转型, 获取对象的 DeclaredField
     * @param object : 子类对象
     * @param fieldName : 父类中的属性名
     * @return 父类中的属性对象
     */
    private static Field getDeclaredField(Object object, String fieldName){

        if (object == null || fieldName == null) {
            return null;
        }

        Field field = null;

        Class<?> clazz = object.getClass();

        for(; clazz != Object.class ; clazz = clazz.getSuperclass()) {
            try {
                field = clazz.getDeclaredField(fieldName);
                return field;
            } catch (Exception e) {
                //这里甚么都不要做！并且这里的异常必须这样写，不能抛出去。
                //如果这里的异常打印或者往外抛，则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }

        return null;
    }

    /**
     * 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
     * @param object : 子类对象
     * @param fieldName : 父类中的属性名
     * @return : 父类中的属性值
     */

    private static Object getFieldValue(Object object, String fieldName){

        if (object == null || fieldName == null) {
            return null;
        }

        //根据 对象和属性名通过反射 调用上面的方法获取 Field对象
        Field field = getDeclaredField(object, fieldName) ;

        if (field != null) {
            //抑制Java对其的检查
            field.setAccessible(true) ;

            try {
                //获取 object 中 field 所代表的属性值
                return field.get(object) ;

            } catch(Exception e) {
                e.printStackTrace() ;
            }
        }

        return null;
    }

    /**
     * 读取对象最底层子对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
     * @param object : 子类对象
     * @param fieldName : 父类中的属性名
     * @return : 父类中的属性值
     */

    private static Object getLastFieldValue(Object object, String fieldName){

        if (object == null || fieldName == null) {
            return null;
        }

        Object objectTemp = null;

        while (object != null) {
            object = getFieldValue(object, fieldName);

            if (object != null) {
                objectTemp = object;
            }
        }

        return objectTemp;
    }

    private static MimeHeaders getReqMimeHeaders(HttpServletRequest request) {
        if (request == null) {
            log.error("HttpServletRequest is null!");
            return null;
        }

        try {
            Object o1 = getLastFieldValue(request, "request");
            Object o2 = getFieldValue(o1, "coyoteRequest");
            MimeHeaders o3 = (MimeHeaders)getFieldValue(o2, "headers");

            return o3;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 增加header信息，key-value键值对儿加入到header中
     * @param request
     * @param key
     * @param value
     */
    public static void addReqHeader(HttpServletRequest request,String key,String value){
        MimeHeaders mimeHeaders = getReqMimeHeaders(request);

        if (mimeHeaders != null) {
            mimeHeaders.addValue(key).setString(value);
        }
    }

    /**
     * 修改header信息，根据key-value键值修改header
     * @param request
     * @param key
     * @param value
     */
    public static void modReqHeader(HttpServletRequest request,String key,String value){
        MimeHeaders mimeHeaders = getReqMimeHeaders(request);

        if (mimeHeaders != null) {
            mimeHeaders.setValue(key).setString(value);
        }
    }

    /**
     * 删除header信息，根据key删除header
     * @param request
     * @param key
     */
    public static void delReqHeader(HttpServletRequest request,String key){
        MimeHeaders mimeHeaders = getReqMimeHeaders(request);

        if (mimeHeaders != null) {
            mimeHeaders.removeHeader(key);
        }
    }
}
